/////////////////////////////////////////////////////////////////////////////
// Name:        types.h
// Author:      Nicolay Giraldo
// Created:     15/12/05
// Copyright:   Nicolay Giraldo
/////////////////////////////////////////////////////////////////////////////

#ifndef __interpreter_H__
#define __interpreter_H__


//WX_DECLARE_STRING_HASH_MAP( value, environment );

class reader
{
public:
	reader(int nparens = 0, int nbackquote = 0) :
		parens(nparens), backquote(nbackquote)
	{
//		wxLogDebug(_T("New reader, parens: %d, backquoted %d"), nparens, backquote);
		rootset = false;
	}
	void init()
	{
//		haschar = false;
		rootset = false;
	}
	int parens;
	int backquote;
	bool rootset;
	static bool haschar;
	static wxChar cbuffer;
	value* read(wxInputStream& istream);
	wxString readToken(wxTextInputStream& tistream);
	value* parseToken(wxString token);
};


void print(value* expr, wxOutputStream& ostream);

wxString printstring(value* expr);

value* eval(value* expr, evalframe* env);

value* apply(value* expr, value* params, evalframe* env);

void guiprint(value* expr, wxTextCtrl& otxtctrl);


class interpreter
{
	public:
	evalframe* currentframe;
	void eval(evalframe* eframe);
};


class MutexGuiLocker
{
	public:
	MutexGuiLocker()
	{wxMutexGuiEnter();}
	~MutexGuiLocker()
	{wxMutexGuiLeave();}
};


class debugger;

class textEditor;


class repl : public wxThread
{
	public:
	//
	repl(wxMutex *mutex, wxCondition *condition, wxThreadKind kind = wxTHREAD_DETACHED)
		: wxThread(kind), guioutput(false)
	{
		m_debugmutex = mutex;
		m_debugcondition = condition;
		
		Create();
	}
	
	~repl()
	{
		wxDELETE(istring);
	}
	reader repl_reader;
	wxInputStream* istream;
	wxOutputStream* ostream;
	wxString *istring;
	textEditor* response;
	bool guioutput;
	void SignalError();
	ExitCode Entry();
//private:
    wxCondition *m_debugcondition;
    wxMutex *m_debugmutex;
};


class debugger : public wxThread
{
	public:
	//
	repl* dbg_repl;
    wxMutex debugmutex;
    wxCondition debugcondition;
	
	debugger(wxThreadKind kind = wxTHREAD_DETACHED)
		: wxThread(kind), debugmutex(), debugcondition(debugmutex)
	{
//		Create();
		debugmutex.Lock();
	}
	ExitCode Entry()
    {
		return debug();
	}
	ExitCode debug()
	{
		debugcondition.Wait();
		
		//debug repl (or other thread) here
		
		return debug();
	}
};


class lispruntime
{
	public:
	globalenvironment globalenv;
    wxMutex globalmutex;
	debugger* maindebugger;
	repl* mainrepl;
	lispruntime() { maindebugger = new debugger(); maindebugger->Create(); maindebugger->Run(); }
	void init_common_lisp();
	void createReplThread() { mainrepl= new repl(&(maindebugger->debugmutex), &(maindebugger->debugcondition)); }
};


extern lispruntime* ngLispRuntime;


#endif
